package com.mf.all.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mf.all.emuns.EnumBaseParams;
import com.mf.all.emuns.enumsPublic.EnumPublicEnableOrDisable;
import com.mf.all.entity.dto.DtoPermission;
import com.mf.all.entity.dto.DtoRole;
import com.mf.all.entity.dto.DtoUser;
import com.mf.all.entity.req.search.user.SearchReqUser;
import com.mf.all.entity.req.user.ReqLogin;
import com.mf.all.entity.req.user.ReqUserUpdatePwd;
import com.mf.all.exception.GraceException;
import com.mf.all.mapper.MapperUser;
import com.mf.all.service.ServicePermission;
import com.mf.all.service.ServiceRole;
import com.mf.all.service.ServiceUser;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import java.util.List;


@Service
public class ImplServiceUser extends ServiceImpl<MapperUser, DtoUser> implements ServiceUser {
    @Resource
    private BCryptPasswordEncoder passwordEncoder;

    @Resource
    private ServiceRole serviceRole;

    @Resource
    private ServicePermission servicePermission;

    /**
     * 参数查询条件
     */
    @Override
    public LambdaQueryWrapper<DtoUser> fillParams(SearchReqUser params) {
        LambdaQueryWrapper<DtoUser> wrapper = loadQw().eq(ObjectUtils.isNotEmpty(params.getStatus()), DtoUser::getStatus, params.getStatus()).eq(ObjectUtils.isNotEmpty(params.getEmail()), DtoUser::getEmail, params.getEmail()).eq(ObjectUtils.isNotEmpty(params.getJobId()), DtoUser::getJobId, params.getJobId()).eq(ObjectUtils.isNotEmpty(params.getDeptId()), DtoUser::getDeptId, params.getDeptId());

        if (StringUtils.hasText(params.getKey())) {
            wrapper.and(qw -> qw.like(DtoUser::getUsername, params.getKey()).or().like(DtoUser::getNick, params.getKey()).or().like(DtoUser::getEmail, params.getKey()));
        }
        return wrapper.orderByDesc(DtoUser::getId);
    }

    /**
     * 根据用户名查询用户
     */
    private DtoUser findByUserName(String username) {
        final LambdaQueryWrapper<DtoUser> wrapper = loadQw().eq(DtoUser::getUsername, username);
        return getOne(wrapper);
    }

    /**
     * 根据岗位id是否有用户
     */
    @Override
    @Transactional
    public boolean isExistByJobId(Integer jobId) {
        final LambdaQueryWrapper<DtoUser> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(DtoUser::getJobId, jobId).last("Limit 1");
        return count(wrapper) > 0;
    }

    /**
     * 根据id查询用户是否存在
     */
    @Override
    public void isExistById(Integer id) {
        final LambdaQueryWrapper<DtoUser> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(DtoUser::getId, id).eq(DtoUser::getStatus, EnumPublicEnableOrDisable.ENABLE.getCode());
        if (ObjectUtils.isEmpty(getOne(wrapper))) {
            GraceException.display("用户不存在");
        }
    }

    /**
     * 根据部门id查询员工数
     */
    @Override
    public long findByDeptIdCount(Integer deptId) {
        final LambdaQueryWrapper<DtoUser> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(DtoUser::getDeptId, deptId).eq(DtoUser::getStatus, EnumPublicEnableOrDisable.ENABLE.getCode());
        return count(wrapper);
    }

    /**
     * 根据部门id查询用户
     */
    @Override
    public List<DtoUser> findByDeptId(Integer deptId) {
        final LambdaQueryWrapper<DtoUser> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(DtoUser::getDeptId, deptId);
        return list(wrapper);
    }

    /**
     * 修改密码
     */
    @Override
    @Transactional
    public void updatePwd(ReqUserUpdatePwd userUpdatePwd, boolean isAdmin) {

        final DtoUser dtoUser1 = getById(userUpdatePwd.getId());
        if (!isAdmin) {
            Assert.state(passwordEncoder.matches(userUpdatePwd.getOldPwd(), dtoUser1.getPassword()), "旧密码错误");
            Assert.state(!userUpdatePwd.getOldPwd().equals(userUpdatePwd.getNewPwd()), "新密码不能与旧密码相同");
        }
        dtoUser1.setPassword(passwordEncoder.encode(userUpdatePwd.getNewPwd()));
        updateById(dtoUser1);
    }


    @Override
    @Transactional
    public DtoUser doCheck(ReqLogin reqLogin) {
        DtoUser user = findByUserName(reqLogin.getUsername());
        Assert.state(user != null, "用户名或密码错误(1), 请检查");
        Assert.state(passwordEncoder.matches(reqLogin.getPassword(), user.getPassword()), "用户名或密码错误(2), 请检查");
        Assert.state(user.getStatus() == 1, "用户已被禁用, 请联系管理员");
        user.setPassword("");
        //执行登录
        StpUtil.login(user.getId());
        // 获取用户角色
        final List<String> dtoRoles =
                serviceRole.selectRolesByUserId(user.getId()).stream().map(DtoRole::getRoleName).toList();

        // 获取用户权限
        final List<String> permissionSet = servicePermission.listByUserId(user.getId()).stream().map(DtoPermission::getCode).toList();
        //缓存用户
        StpUtil.getSession().set(EnumBaseParams.douser.name(), user.getUsername())
                .set(EnumBaseParams.userId.name(), user.getId())
                .set(EnumBaseParams.roles.name(), dtoRoles)
                .set(EnumBaseParams.permissions.name(), List.of("*"))
        ;


        user.setTokenValue(StpUtil.getTokenInfo().tokenValue);
        user.setPermissions(StpUtil.getPermissionList());
        return user;
    }


}